package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruoyi.business.domain.CarPackageAudit;
import com.ruoyi.business.domain.ServiceItem;
import com.ruoyi.business.mapper.CarPackageAuditMapper;
import com.ruoyi.business.service.ICarPackageAuditService;
import com.ruoyi.business.service.IDefinitionNodeService;
import com.ruoyi.business.service.IProcessService;
import com.ruoyi.business.service.IServiceItemService;
import com.ruoyi.business.vo.AuditInfo;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 审核列表Service业务层处理
 *
 * @author gekor
 * @date 2021-07-24
 */
@Service
public class CarPackageAuditServiceImpl implements ICarPackageAuditService {
	@Autowired
	private CarPackageAuditMapper carPackageAuditMapper;
	@Autowired
	private IProcessService processService;
	@Autowired
	private IServiceItemService serviceItemService;
	@Autowired
	private IDefinitionNodeService definitionNodeService;

	@Override
	public CarPackageAudit selectCarPackageAuditByInstanceId(String instanceId) {
		return carPackageAuditMapper.selectCarPackageAuditByInstanceId(instanceId);
	}

	/**
	 * 返回我的已办任务相关汽车套餐审核流程信息
	 * @return
	 */
	@Override
	public List<CarPackageAudit> selectDoneCarPackageAuditList() {
		//根据当前登录用户id，去历史任务中查询他完成的任务对象集合，从任务对象中获取任务名称、完成时间、流程实例id集合
		Long userId = ShiroUtils.getUserId();
		List<HistoricTaskInstance> historicTaskInstanceList = processService.selectDoneTaskList(userId);

		//根据流程实例id集合，去套餐审核表查询相关审核记录信息集合，按页面要求封装必要字段后，返回给页面展示
		List<CarPackageAudit> auditList = new ArrayList<>();
		for (HistoricTaskInstance taskInstance : historicTaskInstanceList) {
			String processInstanceId = taskInstance.getProcessInstanceId();
			CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditByInstanceId(processInstanceId);
			audit.setDoneTaskName(taskInstance.getName());
			audit.setDoneTime(taskInstance.getEndTime());
			audit.setServiceItem(JSON.parseObject(audit.getServiceItemInfo(),ServiceItem.class));
			Integer status = audit.getStatus();
			if (CarPackageAudit.STATUS_IN_ROGRESS.equals(status) || CarPackageAudit.STATUS_REJECT.equals(status)) {// 流程还未结束
				// 根据流程实例id查询正在执行的任务
				Task task = processService.getExecutingTask(processInstanceId);
				audit.setTaskId(task.getId());
			} else {
				audit.setAuditors("流程已结束!");
			}

			auditList.add(audit);
		}

		return auditList;
	}

	/**
	 * 根据当前登录用户查询他的待办任务
	 * @return
	 */
	@Override
	@Transactional
	public List<CarPackageAudit> selectTodoCarPackageAuditList() {
		// 根据当前登录用户查询他待办任务所在的流程实例
		List<String> instanceIds = processService.selectProcessInstanceWithLoginUser();
		if (instanceIds != null && instanceIds.size() > 0){
			List<CarPackageAudit> auditList = carPackageAuditMapper.selectCarPackageAuditByInstanceIds(instanceIds);
			return getCarPackageAudits(auditList);
		}
		return Collections.EMPTY_LIST;
	}

	@Override
	@Transactional
	public int reApply(String taskId, String instanceId) {
		// 更新item表和快照表状态为审核中，更新服务项和套餐信息
		serviceItemService.updateServiceItemById(Long.valueOf(taskId),ServiceItem.AUDITSTATUS_AUDITING);
		ProcessInstance instance = processService.selectProcessInstanceByTaskId(taskId);
		carPackageAuditMapper.updateCarPackageAuditByInstanceId(instance.getId(),CarPackageAudit.STATUS_IN_ROGRESS);
		// 完成任务，设置下个节点的审核候选人
		Task nextTask = processService.completeTaskByAudit(taskId, true, null, instanceId);
		if (nextTask != null) {
			CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditByInstanceId(instance.getId());
			// 根据节点key查找节点审核人，并设置审核人
			selectAuditorsByTaskDefinitionKey(nextTask, audit);
			carPackageAuditMapper.updateCarPackageAudit(audit);
		}
		return 1;
	}

	/**
	 * 修改表单，提交
	 * @param serviceItem
	 * @param auditId
	 * @return
	 */
	@Override
	@Transactional
	public int reEditSave(ServiceItem serviceItem, Long auditId) {
		// 根据快照表id查找快照对象，获取item对象并更新，再重新插入快照记录和item表
		CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditById(auditId);
		ServiceItem serviceItemSelect = JSON.parseObject(audit.getServiceItemInfo(), ServiceItem.class);
		serviceItemSelect.setName(serviceItem.getName());
		serviceItemSelect.setOriginalPrice(serviceItem.getOriginalPrice());
		serviceItemSelect.setDiscountPrice(serviceItem.getDiscountPrice());
		serviceItemSelect.setServiceCatalog(serviceItem.getServiceCatalog());
		serviceItemSelect.setInfo(serviceItem.getInfo());
		serviceItemSelect.setAuditStatus(ServiceItem.AUDITSTATUS_REPLY);

		audit.setServiceItemInfo(JSON.toJSONString(serviceItemSelect));
		carPackageAuditMapper.updateCarPackageAudit(audit);
		serviceItemService.updateServiceItem(serviceItemSelect);

		return 1;
	}

	/**
	 * 完成审批，保存审批数据，修改相应表状态
	 * @return
	 * @param taskId
	 * @param auditStatus
	 * @param comment
	 * @param itemId
	 */
	@Override
	@Transactional
	public int doAudit(String taskId, boolean auditStatus, String comment, Long itemId) {
		// 根据taskId找到对应的task
		// 认领、审批：给流程变量shopOwnerAudit设置布尔值，设置批注信息,完成任务，
		ProcessInstance instance = processService.selectProcessInstanceByTaskId(taskId);
		Task nextTask = processService.completeTaskByAudit(taskId,auditStatus,comment,instance.getId());
		// 判断流程是否结束
		if (nextTask == null) {
			// 如果结束，修改养修表对应状态、快照表对应状态为审核通过，快照表审核人置空
			serviceItemService.updateServiceItemById(itemId,ServiceItem.AUDITSTATUS_APPROVED);
			carPackageAuditMapper.updateCarPackageAuditByInstanceId(instance.getProcessInstanceId(),CarPackageAudit.STATUS_PASS);
		} else {
			// 如果没有结束，设置下一节点的人
			CarPackageAudit audit = carPackageAuditMapper.selectCarPackageAuditByInstanceId(instance.getId());
			if (auditStatus) {	// 如果审核通过，给下一节点设置审核候选人
				// 根据节点key查找节点审核人，并设置审核人
				selectAuditorsByTaskDefinitionKey(nextTask, audit);
			} else { // 如果审核拒绝，给下一节点（申请人重新申请）设置委托人为发起人，并设置养修表、快照表状态和下一节点审核人
				processService.addAssignee(nextTask.getId(),audit.getCreateBy());
				audit.setAuditors(audit.getCreateByName());
				audit.setStatus(CarPackageAudit.STATUS_REJECT);
				serviceItemService.updateServiceItemById(itemId,ServiceItem.AUDITSTATUS_REPLY);
			}
			carPackageAuditMapper.updateCarPackageAudit(audit);
		}

		return 1;
	}

	/**
	 * 根据节点key查找节点审核人，并设置审核人
	 * @param nextTask
	 * @param audit
	 */
	private void selectAuditorsByTaskDefinitionKey(Task nextTask, CarPackageAudit audit) {
		List<SysUser> userList = definitionNodeService.selectAuditorsByNodeKey(nextTask.getTaskDefinitionKey());
		Long[] userIds = userList.stream().map(SysUser::getUserId).toArray(Long[]::new);
		List<String> userNames = userList.stream().map(SysUser::getUserName).collect(Collectors.toList());
		for (Long userId : userIds) {
			processService.addCandidateUser(nextTask.getId(),userId);
		}
		String auditors = JSON.toJSONString(userNames);
		audit.setAuditors(auditors);
	}

	/**
	 * 查询审核列表
	 *
	 * @param id 审核列表ID
	 * @return 审核列表
	 */
	@Override
	public CarPackageAudit selectCarPackageAuditById(Long id) {
		return carPackageAuditMapper.selectCarPackageAuditById(id);
	}


	/**
	 * 对从数据库中查询处理的套餐审核记录对象中的字段进行完善，便于页面展示
	 * @param auditList
	 * @return
	 */
	private List<CarPackageAudit> getCarPackageAudits(List<CarPackageAudit> auditList) {
		for (CarPackageAudit audit : auditList) {
			String serviceItemInfo = audit.getServiceItemInfo();
			ServiceItem serviceItem = JSON.parseObject(serviceItemInfo, ServiceItem.class);
			audit.setServiceItem(serviceItem);
			Task executingTask = processService.getExecutingTask(audit.getInstanceId());// 获取当前任务
			if (executingTask != null) {
				audit.setTaskName(executingTask.getName());
				audit.setTaskId(executingTask.getId());
			}
		}
		return auditList;
	}

	/**
	 * 查询审核列表列表
	 *
	 * @param carPackageAudit 审核列表
	 * @return 审核列表
	 */
	@Override
	@Transactional
	public List<CarPackageAudit> selectCarPackageAuditList(CarPackageAudit carPackageAudit) {
        List<CarPackageAudit> auditList = null;
        if (!ShiroUtils.getSubject().hasRole("admin")) {
            carPackageAudit.setCreateBy(String.valueOf(ShiroUtils.getUserId()));
        }
		auditList = carPackageAuditMapper.selectCarPackageAuditList(carPackageAudit);
		return getCarPackageAudits(auditList);
	}

	/**
	 * 新增审核列表
	 *
	 * @param carPackageAudit 审核列表
	 * @return 结果
	 */
	@Override
	public int insertCarPackageAudit(CarPackageAudit carPackageAudit) {
		carPackageAudit.setCreateTime(DateUtils.getNowDate());
		return carPackageAuditMapper.insertCarPackageAudit(carPackageAudit);
	}

	/**
	 * 修改审核列表
	 *
	 * @param carPackageAudit 审核列表
	 * @return 结果
	 */
	@Override
	public int updateCarPackageAudit(CarPackageAudit carPackageAudit) {
		return carPackageAuditMapper.updateCarPackageAudit(carPackageAudit);
	}

	/**
	 * 删除审核列表对象
	 *
	 * @param ids 需要删除的数据ID
	 * @return 结果
	 */
	@Override
	public int deleteCarPackageAuditByIds(String ids) {
		return carPackageAuditMapper.deleteCarPackageAuditByIds(Convert.toStrArray(ids));
	}

	@Override
	@Transactional
	public int revokeAudit(String instanceId, Long packageId) { //撤销审核
		// 修改养修服务表 和 套餐审核表 对应项状态，套餐审核表审核人置空
		carPackageAuditMapper.updateCarPackageAuditByInstanceId(instanceId, CarPackageAudit.STATUS_CANCEL);
		int count = serviceItemService.updateServiceItemById(packageId, ServiceItem.AUDITSTATUS_INIT);
		// 删除流程实例
		processService.deleteProcessInstance(instanceId);
		return count;
	}

	/**
	 * 查询审批历史记录
	 *
	 * @param instanceId
	 * @return
	 */
	@Override
	public List<AuditInfo> selectHistoricAudit(String instanceId) {
		return processService.selectHistoricAudit(instanceId);
	}

	/**
	 * 删除审核列表信息
	 *
	 * @param id 审核列表ID
	 * @return 结果
	 */
	@Override
	public int deleteCarPackageAuditById(Long id) {
		return carPackageAuditMapper.deleteCarPackageAuditById(id);
	}
}
